#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@File    ：sms_un_comp_v1.py
@IDE     ：PyCharm 
@Author  ：lmy
@Date    ：2024/8/6 21:06 
'''

import os
from feature_set.sms.utils.data_process import *
from feature_set.sms.utils.data_utils import *
from feature_set.base_feature import BaseFeature, RequstData
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import math
import warnings


class SmsUnCompV1:
    @staticmethod
    def extract_cnt_feature(data, df_check):
        """
        cnt模块:计算基础统计单位的数量以及占比
        :return: dict
        """
        sms_feature_res = {}
        # 周末工作日
        time_type = 'date_period'
        for t in WEEK_TYPES:
            comp_df = df_check[df_check[time_type] == t]
            all_df = data[data[time_type] == t]
            sms_feature_res = gen_cnt_fea(all_df, comp_df, t, sms_feature_res)

        # 不同时间窗口
        time_type = 'time_diff'
        for t in TIME_INTERVALS:
            if t == 'all':
                comp_df = df_check.copy()
                all_df = data.copy()
            else:
                comp_df = df_check[df_check[time_type] < t]
                all_df = data[data[time_type] < t]
                t = 'd' + str(t)
            sms_feature_res = gen_cnt_fea(all_df, comp_df, t, sms_feature_res)

        # 每天不同时间段
        time_type = 'hour'
        for t in TIME_PERIODS:
            comp_df = df_check[(df_check[time_type] >= t[0]) & (df_check[time_type] <= t[1])]
            all_df = data[(data[time_type] >= t[0]) & (data[time_type] <= t[1])]
            sms_feature_res = gen_cnt_fea(all_df, comp_df, t[-1], sms_feature_res)

        # 是否已读
        for t in READ_TYPE:
            comp_df = df_check[df_check['read'] == t]
            all_df = data[data['read'] == t]
            sms_feature_res = gen_cnt_fea(all_df, comp_df, 'read_' + t, sms_feature_res)

        return sms_feature_res

    @staticmethod
    def extract_day_feature(df_check):
        """
        计算按天聚合的相关特征
        :return:
        """
        sms_feature_res = {}
        time_type = 'time_diff'

        # 联系密度
        for t in TIME_INTERVALS:
            if t != 'all':
                comp_df = df_check[df_check[time_type] < t]
                density = calc_density(comp_df, t)
                sms_feature_res[f'density_d{t}'] = density

        for t in TIME_INTERVALS:
            if t == 'all':
                comp_df = df_check.copy()
            else:
                comp_df = df_check[df_check[time_type] < t]
                t = 'd' + str(t)

            # 计算联系密度,聚合天数、连续空档数和连续有值数等相关特征
            # 聚合之后，每一天的 cnt的 max/min/avg/sd
            res_agg = calc_agg_fea(comp_df)
            for i in res_agg:
                sms_feature_res[f'{i}_{t}'] = res_agg[i]

            # 计算连续和空档相关特征
            res_con = calc_continue(comp_df, t)
            for i in res_con:
                if 'long' not in i:
                    sms_feature_res[f'{i}_{t}'] = res_con[i]

        return sms_feature_res

    @staticmethod
    def extract_se_feature(df_check):
        """
        se(开始结束)模块:
        :return:
        """
        sms_feature_res = {}
        # 计算se、ae、as特征
        res_se = calc_se_fea(df_check)
        for se_type in SE_TYPE:
            sms_feature_res[f'{se_type}_days_diff'] = res_se[se_type]
        # 计算cnt
        res_cnt = calc_cnt_fea(df_check)
        # 计算cnt/ 开始 - 结束 天数差
        for fea in FEA_LST:
            cnt = res_cnt[fea]
            se = sms_feature_res['es_days_diff']
            sms_feature_res[f'{fea}_to_es_days_diff_rto'] = cnt / se if se > 0 else -999

        # 计算去掉空档的se相关特征
        if df_check.shape[0] != 0:
            tmp_day = df_check['time_day'].unique()
            sms_time_lst = [datetime.strptime(i, '%Y-%m-%d') for i in sorted(tmp_day)]
            first_date_drop30 = sms_time_lst[0]
            first_date_drop60 = sms_time_lst[0]
            for i in range(1, len(sms_time_lst)):
                diff_day = (sms_time_lst[i] - sms_time_lst[i - 1]).days - 1
                if diff_day >= 60:
                    first_date_drop60 = sms_time_lst[i]
                if diff_day >= 30:
                    first_date_drop30 = sms_time_lst[i]

            drop_types = {'drop30': str(first_date_drop30)[:10], 'drop60': str(first_date_drop60)[:10]}
            for drop in drop_types:
                tmp_df = df_check[df_check['time_day'] >= drop_types[drop]]
                # 计算se、ae、as特征
                tmp_res_se = calc_se_fea(tmp_df)
                for se_type in SE_TYPE:
                    sms_feature_res[f'{se_type}_days_diff_{drop}'] = tmp_res_se[se_type]
                # 计算cnt
                tmp_res_cnt = calc_cnt_fea(tmp_df)
                # 计算cnt/ 开始 - 结束 天数差
                for fea in FEA_LST:
                    cnt = tmp_res_cnt[fea]
                    se = sms_feature_res[f'es_days_diff_{drop}']
                    sms_feature_res[f'{fea}_to_es_days_diff_rto_{drop}'] = cnt / se if se > 0 else -999
        else:
            for drop in ['drop30', 'drop60']:
                # 计算se、ae、as特征
                for se_type in SE_TYPE:
                    sms_feature_res[f'{se_type}_days_diff_{drop}'] = -999
                # 计算cnt/ 开始 - 结束 天数差
                for fea in FEA_LST:
                    sms_feature_res[f'{fea}_to_es_days_diff_rto_{drop}'] = -999

        return sms_feature_res

    @staticmethod
    def extract_dod_feature(df_check):
        """"
        计算环比和环差
        """
        sms_feature_res = {}

        for i in WINDOW_LST:
            for fea in FEA_LST:
                if fea == 'word':
                    tmp_df = df_check.explode('word')
                else:
                    tmp_df = df_check.copy()

                sms_feature_res = calc_dod_cnt_rto(tmp_df, i, fea, sms_feature_res)
                sms_feature_res = calc_dod_cnt_rto(tmp_df, i, fea, sms_feature_res)

        return sms_feature_res

    @staticmethod
    def extract_overdue_feature(df_check, country_code):
        """"
        计算逾期金额、逾期天数、还款金额
        """
        sms_feature_res = {}
        columns_lst = df_check.columns.tolist()
        if df_check.shape[0] != 0:
            # df_check['overdue_days'] = df_check['body'].apply(lambda x: calc_overdue_info2(x)[0])
            # df_check['overdue_amt'] = df_check['body'].apply(lambda x: calc_overdue_info2(x)[1])
            # df_check['overdue_days'] = df_check.apply(
            #     lambda x: calc_overdue_info(x['body'])[0] if pd.isna(x['overdue_days']) else x['overdue_days'], axis=1)
            # df_check['overdue_amt'] = df_check.apply(
            #     lambda x: calc_overdue_info(x['body'])[1] if pd.isna(x['overdue_amt']) else x['overdue_amt'], axis=1)
            df_check['overdue_days'] = df_check['body'].apply(lambda x: calc_overdue_days(x, country_code))
            df_check['overdue_amt'] = df_check['body'].apply(lambda x: calc_overdue_amt(x, country_code))
            df_check['repay_amt'] = df_check['body'].apply(lambda x: calc_repay_amount(x, country_code))
        else:
            df_check = pd.DataFrame(columns=columns_lst + ['overdue_days', 'overdue_amt', 'repay_amt'])

        # 不同时间窗口
        time_type = 'time_diff'
        for t in TIME_INTERVALS:
            if t == 'all':
                comp_df = df_check.copy()
            else:
                comp_df = df_check[df_check[time_type] < t]
                t = 'd' + str(t)
            tmp_res = calc_overdue_fea(comp_df, t)
            sms_feature_res.update(tmp_res)

        return sms_feature_res

    @staticmethod
    def extract_pay_feature(df_check, country_code):
        """"
        计算逾支付金额
        """
        sms_feature_res = {}
        columns_lst = df_check.columns.tolist()
        if df_check.shape[0] != 0:
            df_check['pay_amt'] = df_check['body'].apply(lambda x: calc_pay_amount(x, country_code))
        else:
            df_check = pd.DataFrame(columns=columns_lst + ['pay_amt'])

        # 不同时间窗口
        time_type = 'time_diff'
        for t in TIME_INTERVALS:
            if t == 'all':
                comp_df = df_check.copy()
            else:
                comp_df = df_check[df_check[time_type] < t]
                t = 'd' + str(t)
            tmp_res = calc_finance_fea(comp_df, t, 'pay_amt')
            sms_feature_res.update(tmp_res)

        return sms_feature_res

    @staticmethod
    def extract_balance_feature(df_check, country_code):
        """"
        计算余额
        """
        sms_feature_res = {}
        columns_lst = df_check.columns.tolist()
        if df_check.shape[0] != 0:
            df_check['balance_amt'] = df_check['body'].apply(lambda x: calc_balance_amount(x, country_code))
        else:
            df_check = pd.DataFrame(columns=columns_lst + ['balance_amt'])

        # 不同时间窗口
        time_type = 'time_diff'
        for t in TIME_INTERVALS:
            if t == 'all':
                comp_df = df_check.copy()
            else:
                comp_df = df_check[df_check[time_type] < t]
                t = 'd' + str(t)
            tmp_res = calc_finance_fea(comp_df, t, 'balance_amt')
            sms_feature_res.update(tmp_res)

        return sms_feature_res
